type DebouncedFunction<T extends (...args: any[]) => any> = {
  (...args: Parameters<T>): void;
  cancel: () => void;
};

function debounce<T extends (...args: any[]) => any>(
  func: T,
  delay: number
): DebouncedFunction<T> {
  let timer: NodeJS.Timeout;

  const debounced: DebouncedFunction<T> = function (this: any, ...args: Parameters<T>) {
    const context = this;

    clearTimeout(timer);

    timer = setTimeout(() => {
      func.apply(context, args);
    },
    );
  };

  debounced.cancel = function () {
    clearTimeout(timer);
  };

  return debounced;
}
export default debounce;